package hibari.client;

import static com.google.gwt.query.client.GQuery.$;
import hibari.client.model.ClientServices;
import hibari.client.ui.Japanese;
import hibari.client.ui.SelectionHandler;
import hibari.client.ui.Tabs;
import hibari.client.ui.WeekBrowser;
import hibari.client.ui.WeekViewer;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.query.client.Function;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Book implements EntryPoint {
	private static Book instance;

	public static Book getInstance() {
		return instance;
	}

	private RootPanel rightPanel;
	private RootPanel leftPanel;
	private WeekBrowser weekBrowser;
	private WeekViewer weekViewer;
	private HTMLPanel contactPanel;
	private HTMLPanel aboutPanel;
	private Tabs tabs;
	protected HTMLPanel payResultPanel;

	public Book() {
		instance = this;
	}

	public void ensureWeekViewerIsShowing() {
		if (this.weekViewer.getParent() == null) {
			this.rightPanel.clear();
			this.rightPanel.add(this.weekViewer);
		}
	}

	public RootPanel getLeftPanel() {
		return this.leftPanel;
	}

	public RootPanel getRightPanel() {
		return this.rightPanel;
	}

	protected void handleHistoryChanged(ValueChangeEvent<String> event) {
		handleMode(event.getValue());
	}

	public void showLoading() {
		this.rightPanel.addStyleName("right-page-loading");
	}

	public void hideLoading() {
		this.rightPanel.removeStyleName("right-page-loading");
	}

	private void handleMode(String mode) {
		if (mode.startsWith("week")) {
			this.tabs.setActiveTab(0);
			String numberPart = mode.substring(4);
			ensureWeekViewerIsShowing();
			try {
				int weekNo = Integer.parseInt(numberPart);
				this.weekViewer.setWeek(weekNo);
			} catch (Exception e) {
				showHomeMode();
			}
		} else if (mode.equals("contact")) {
			showContact();

		} else if (mode.equals("about")) {
			showAboutMode();

		} else if (mode.equals("pay-result")) {
			showPayResult();
		} else {
			showHomeMode();
		}
	}

	@Override
	public void onModuleLoad() {
		this.rightPanel = RootPanel.get("right-page");
		this.leftPanel = RootPanel.get("left-page");

		$("#logo-icon").click(new Function() {
			public void f() {
				showAboutMode();
			}
		});

		this.weekBrowser = new WeekBrowser();
		this.weekBrowser.setSelectionHandler(new SelectionHandler<Integer>() {
			@Override
			public void selectionChanged(Integer newSelection) {
				showWeek(newSelection);
			}
		});
		this.leftPanel.add(this.weekBrowser);

		this.weekViewer = new WeekViewer();

		String token = History.getToken();
		History.addValueChangeHandler(new ValueChangeHandler<String>() {
			@Override
			public void onValueChange(ValueChangeEvent<String> event) {
				handleHistoryChanged(event);
			}
		});

		if (token == null || token.isEmpty()) {
			token = "home";
		}
		this.tabs = new Tabs(RootPanel.get());
		this.tabs.setTabHandler(new SelectionHandler<Integer>() {
			@Override
			public void selectionChanged(Integer newSelection) {
				handleTabSelected(newSelection);
			}

		});

		this.weekBrowser.loadAndShowContents();

		handleMode(token);
	}

	protected void handleTabSelected(Integer newSelection) {
		if (newSelection == Tabs.TAB_HOME) {
			History.newItem("home");
		} else if (newSelection == Tabs.TAB_ABOUT) {
			History.newItem("about");
		} else if (newSelection == Tabs.TAB_CONTACT) {
			History.newItem("contact");
		}
	}

	public void showAboutMode() {
		History.newItem("about");
		this.rightPanel.clear();
		this.tabs.setActiveTab(Tabs.TAB_ABOUT);
		if (this.aboutPanel != null) {
			this.rightPanel.add(this.aboutPanel);
			return;
		}

		showLoading();

		String url = "/about_en.html";
		if (Japanese.isUserJapanese()) {
			url = "/about_ja.html";
		}

		try {
			RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url));
			builder.sendRequest(null, new RequestCallback() {

				@Override
				public void onError(Request request, Throwable exception) {
					Book.this.aboutPanel = null;
					exception.printStackTrace();
				}

				@Override
				public void onResponseReceived(Request request, Response response) {
					if (200 == response.getStatusCode()) {
						Book.this.aboutPanel = new HTMLPanel(response.getText());
						Book.this.rightPanel.add(Book.this.aboutPanel);
						hideLoading();
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void showPayResult() {
		History.newItem("pay-result");
		this.rightPanel.clear();
		if (this.payResultPanel != null) {
			this.rightPanel.add(this.payResultPanel);
			return;
		}

		try {
			RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode("/PayResult.html"));
			builder.sendRequest(null, new RequestCallback() {

				@Override
				public void onError(Request request, Throwable exception) {
					Book.this.payResultPanel = null;
					exception.printStackTrace();
				}

				@Override
				public void onResponseReceived(Request request, Response response) {
					if (200 == response.getStatusCode()) {
						Book.this.payResultPanel = new HTMLPanel(response.getText());
						Book.this.payResultPanel.setHeight("100%");
						Book.this.rightPanel.add(Book.this.payResultPanel);
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void showContact() {
		History.newItem("contact");
		this.rightPanel.clear();
		this.tabs.setActiveTab(Tabs.TAB_CONTACT);
		if (this.contactPanel != null) {
			this.rightPanel.add(this.contactPanel);
			return;
		}

		String url = "/contact_en.html";
		if (Japanese.isUserJapanese()) {
			url = "/contact_ja.html";
		}

		showLoading();
		try {
			RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url));
			builder.sendRequest(null, new RequestCallback() {

				@Override
				public void onError(Request request, Throwable exception) {
					Book.this.contactPanel = null;
					exception.printStackTrace();
				}

				@Override
				public void onResponseReceived(Request request, Response response) {
					if (200 == response.getStatusCode()) {
						Book.this.contactPanel = new HTMLPanel(response.getText());
						contactPanel.addStyleName("right-page-content");
						Book.this.rightPanel.add(Book.this.contactPanel);
						hideLoading();
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void showHomeMode() {
		History.newItem("home");
		this.rightPanel.clear();
		this.rightPanel.add(this.weekViewer);

		ClientServices.weekService.getLastWeekNumber(new AsyncCallback<Integer>() {
			@Override
			public void onFailure(Throwable caught) {

			}

			@Override
			public void onSuccess(Integer result) {
				if (result == null) {
					return;
				}
				Book.this.weekViewer.setWeek(result);
			}
		});
	}

	public void showWeek(Integer newSelection) {
		this.tabs.setActiveTab(Tabs.TAB_HOME);
		ensureWeekViewerIsShowing();
		Book.this.weekViewer.setWeek(newSelection);
		History.newItem("week" + newSelection, false);
	}
}
